package io.dy.custom_pool;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;

import static io.dy.utils.ThreadUtils.printThreadLog;

/**
 * @author : dmj
 * @date: 2024/7/11 1:39 下午
 * @description: 自定义线程池
 */
public class CustomThreadPool {

    /**
     * 任务队列
     */
    private final CustomBlockQueue<Runnable> taskQueue;

    /**
     * 线程集合
     */
    private final HashSet<Worker> workers;

    /**
     * 核心线程数大小
     */
    private final int coreSize;

    /**
     * 任务的超时时间
     */
    private final long timeout;

    /**
     * 时间单位
     */
    private final TimeUnit unit;

    /**
     * 拒绝策略
     */
    private final CustomRejectPolicy<Runnable> policy;


    public void execute(Runnable runnable){
        //判断线程数量是否大于核心线程数 若没有 则直接创建线程；否则加入任务队列
        synchronized (workers){
            if(workers.size() < coreSize){
                Worker worker = new Worker(runnable);
                printThreadLog("新增worker" + worker + ";任务为:" +runnable);
                //加入线程集合
                workers.add(worker);
                //线程启动
                worker.start();
            }else{
                //否则加入任务队列
                //printThreadLog("任务加入任务队列" + runnable);
                //taskQueue.add(runnable);
                taskQueue.addWithRejectPolicy(policy, runnable);
            }
        }
    }


    public CustomThreadPool(int coreSize, long timeout, TimeUnit unit, int queueCapacity, CustomRejectPolicy<Runnable> policy){
        this.coreSize = coreSize;
        this.timeout = timeout;
        this.unit = unit;
        this.policy = policy;
        workers = new HashSet<>();
        taskQueue = new CustomBlockQueue<>(queueCapacity);
    }

    public CustomThreadPool(){
        this.coreSize = 2;
        this.timeout = 10;
        this.unit = TimeUnit.SECONDS;
        this.policy = (queue,task)->{};
        workers = new HashSet<>();
        taskQueue = new CustomBlockQueue<>(10);
    }

    class Worker extends Thread{

        private Runnable task;

        public Worker(Runnable runnable) {
            this.task = runnable;
        }

        @Override
        public void run() {
            //执行任务
                //1、判断task是否为空 不为空直接执行
                //2、task为空 去队列获取任务执行
            //while (task != null || (task = taskQueue.take()) != null){
            while (task != null || (task = taskQueue.takeWithTimeout(timeout, unit)) != null){
                try{
                    printThreadLog("任务正在执行。。。" + task);
                    task.run();
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    task = null;
                }
            }

            //执行到这边 标识 任务队列中无任务可执行 则移除改线程
            synchronized (workers){
                printThreadLog("worker被移除。。。" + this);
                workers.remove(this);
            }
        }
    }
}
